package initialize

import (
	"fmt"
	"grpc-server/global"
	"grpc-server/utils"
	"log"
	"sync"

	"github.com/google/uuid"
	"github.com/hashicorp/consul/api"
)

var clientOnce sync.Once
var consulClient *api.Client
var serviceID string

// notSet 若没有设置consul就不做操作
func notSet() bool {
	consulConfig := global.CONFIG.Consul
	return consulConfig.ConsulAddr == ""
}

// 连接注册中心
func conn() {
	consulConfig := global.CONFIG.Consul
	serviceID = uuid.New().String()

	cfg := api.DefaultConfig()
	cfg.Address = consulConfig.ConsulAddr

	var err error
	consulClient, err = api.NewClient(cfg)
	if err != nil {
		log.Fatalf("连接注册中心失败 %s", err.Error())
	}
}

// ConsulRegister 服务注册
func ConsulRegister() {
	if ye := notSet(); ye {
		return
	}

	conn()
	consulConfig := global.CONFIG.Consul

	// 生成注册对象
	register := new(api.AgentServiceRegistration)
	register.ID = serviceID
	register.Address = utils.GetLocalIp()
	register.Port = utils.GetFreePort()
	register.Name = consulConfig.Name
	register.Tags = consulConfig.Tags

	// 生成对应的检查对象
	register.Check = &api.AgentServiceCheck{
		GRPC:                           utils.GetIpPort(),
		Timeout:                        "5s",  // 超时
		Interval:                       "5s",  // 检查间隔
		DeregisterCriticalServiceAfter: "10s", //注册失败10s后取消注册
	}

	// 开始注册
	err := consulClient.Agent().ServiceRegister(register)
	if err != nil {
		log.Fatalf("服务注册失败 %s", err.Error())
	} else {
		global.LOG.Info("注册成功")
	}
}

// ConsulCancelRegister 服务注销
func ConsulCancelRegister() {
	if ye := notSet(); ye {
		return
	}

	err := consulClient.Agent().ServiceDeregister(serviceID)
	if err != nil {
		log.Fatalf("服务注销失败 %s", err.Error())
	}
}

// ConsulServices 全部服务
func ConsulServices() {
	data, err := consulClient.Agent().Services()
	if err != nil {
		panic(err)
	}
	for key, value := range data {
		fmt.Println(key, value)
	}
}

// ConsulFilter 服务过滤
func ConsulFilter(serviceName string) map[string]*api.AgentService {
	data, _ := consulClient.Agent().ServicesWithFilter("Service == " + serviceName) // 通过服务名称过滤
	return data
}

// ServiceTarget 服务地址
func ServiceTarget(serviceName string) string {
	consulConfig := global.CONFIG.Consul
	return "consul://" + consulConfig.ConsulAddr + "/" + serviceName
}
